package xfuzzy.alg_genetico.indeterminado.xfghlOld.model;

import java.util.Random;

//import org.apache.log4j.Logger;

//import xfuzzy.xfghl.model.spec.XfghlRuleSet;

public class XfghlGeneticAlgorithm2 {

	/**
	 * Logger
	 */
	//private static Logger logger = Logger.getLogger("Algoritmo");

	/**
	 * N�mero aleatorio
	 */
	private Random random;

	
	/**
	 * Configuraci�n del sistema
	 */
	private XfghlConfig config;
	
	
	/**
	 * Mejor cromosoma despues de terminar con el gen�tico
	 */
	private XfghlChromosome chromBest=null;
	
	/**
	 * Constructor
	 */
	public XfghlGeneticAlgorithm2(XfghlConfig config) {
		
		this.config=config;
		this.random=XfghlSinglRandom.getRandom();

	}
	
	/**
	 * M�todo que lanza el algoritmo gen�tico
	 */
	@SuppressWarnings("unused")
	public void start()
	{
		
		/* Algoritmo Genetico Con elitismo */		 
		
		 //N�mero de generaciones
		 int numGenerations=this.config.getNumGenerations();
		 //N�mero de cromosomas
		 int numChrom=this.config.getNumChrom();

		 //Generar una poblacion inicial
		 XfghlGeneration antGen=new XfghlGeneration(this.config,true);
		 
		 //Entrenamos la poblaci�n inicial
		 XfghlLearnSpecif.setConfig(this.config);
		 XfghlLearnSpecif.setGeneration(antGen);		 
		 XfghlLearnSpecif.learningSpecif();

		 //Ordenamos la poblaci�n
		 antGen.orderPoblation();
		 //logger.info("Generacion inicial:\n"+antGen.toString());		 
		 
		 //Probabilidad de mutaci�n
		 double probMut=this.config.getProbMut();		 
		 //Probabilidad de cruce
		 double probCruce=this.config.getProbCross();
		 
		 //Evolucionamos y obtenemos las generaciones
	   	 for(int i=0;i<numGenerations-1;i++){
				
				//Producir nueva generacion
				XfghlGeneration newGen=new XfghlGeneration(this.config,false);
				
				//A�adimos el elitismo, los dos primeros individuos
				//newGen.addChromosome(antGen.getChromosome(0));
				//newGen.addChromosome(antGen.getChromosome(1));
				
				
				//A�adimos el elitismo, los dos primeros individuos
				XfghlChromosome [] elite=antGen.twoBest();
				newGen.addChromosome(elite[0]);
				newGen.addChromosome(elite[1]);
				
				
				//Ciclo Reproductivo para generar la nueva poblaci�n
				for(int j=0;j<(numChrom/2)-1;j++)
				{
					//Seleccionar dos individuos de la anterior generacion,
					//para el cruce (probabilidad de seleccion proporcional
					//a la funcion de evaluacion del individuo)					
					XfghlChromosome c1=antGen.getRandomChromosome(); 
					XfghlChromosome c2=antGen.getRandomChromosome();
					XfghlChromosome cross1;
					XfghlChromosome cross2;					
										
					//Cruzar con cierta probabilidad los dos
					//individuos obteniendo dos descendientes.
					double probCross=this.random.nextFloat();
					if(probCross<=probCruce)
					{   
						XfghlChromosome [] chrom=c1.cross(c2);
						cross1=chrom[0];
						cross2=chrom[1];
						//logger.info("Cruce: "+c1.toString()+" con "+c2.toString()+". cross1: "+cross1.toString()+" cross2: "+cross2.toString());
					}
					else
					{  //Hacemos una copia
						cross1=new XfghlChromosome(c1);
						cross2=new XfghlChromosome(c2);	
					}
					
					double probMutat=this.random.nextFloat();
					//Mutar los dos descendientes con cierta probabilidad.
					if(probMutat<=probMut)
					{
						String sCross1=cross1.toString();
						cross1.mutate2();
						//logger.info(" Mutamos: "+sCross1+" a "+cross1.toString());
					}
					
					probMutat=this.random.nextFloat();
					if(probMutat<=probMut)
					{
					 String sCross2=cross2.toString();
					   cross2.mutate2();	
					   //logger.info(" Mutamos: "+sCross2+" a "+cross2.toString());
					}

					//Insertar los dos descendientes mutados en la nueva generacion
					//si ya existe el individuo generamos uno aleatorio
					while(newGen.containChromosome(cross1))
					{
						cross1=new XfghlChromosome(config,true);
					}
					newGen.addChromosome(cross1);

					//Insertar los dos descendientes mutados en la nueva generacion
					//si ya existe el individuo generamos uno aleatorio
					while(newGen.containChromosome(cross2))
					{
						cross2=new XfghlChromosome(config,true);
					}					
					newGen.addChromosome(cross2);					
				}
				
				//logger.info("Antes entrenar generaci�n "+i+":"+antGen.toString());		
				
				//Computar la funcion de evaluacion de la nueva generaci�n 
				XfghlLearnSpecif.setGeneration(newGen);
				XfghlLearnSpecif.learningSpecif();
				
				//Ordenamos la nueva poblaci�n
				newGen.orderPoblation();
											
				//Avanzamos en la poblaci�n
				antGen=newGen;
				
				//logger.info("Generacion "+i+":"+antGen.toString());				
			}
	   	//como esta ordenado el mejor cromosoma es el que estar� en la posici�n 0
		this.chromBest=antGen.getChromosome(0);
		
		//logger.info("Mejor Cromosoma de todos: "+this.chromBest.toString()+"("+this.chromBest.getFinalError()+" ).");
	}

	public XfghlChromosome getChromBest() {
		return chromBest;
	}

	public void setChromBest(XfghlChromosome chromBest) {
		this.chromBest = chromBest;
	} 

}

